﻿using NUnit.Framework;
using TI_BLE_HCI_ClientLib.DataEntities.Advertising;
using TI_BLE_HCI_ClientLib.DataEntities.Advertising.ManufacturerSpecificDataEntities;

namespace TI_BLE_HCI_ClientLib.Tests
{
    [TestFixture]
    public class AdvertisingAndScanResponseDataDecodingTester
    {
        [Test]
        public void Decode_AdvertisingAndScanResponseData()
        {
            string hex = "02 01 06 1A FF 4C 00 02 15 E2 C5 6D B5 DF FB 48 " +
                          "D2 B0 60 D0 F5 A7 10 96 E0 00 01 00 00 C6 ";

            byte[] buf = TestHelpers.StringToByteArray(hex);

            AdvertisingAndScanResponseData advertisingAndScanResponseData = AdvertisingAndScanResponseDataParser.Parse(buf);

            Assert.IsNotNull(advertisingAndScanResponseData);

            Assert.AreEqual(2, advertisingAndScanResponseData.AdvertisingDataStructures.Length);
            Assert.IsInstanceOf<FlagsAdvertisingDataStructure>(advertisingAndScanResponseData.AdvertisingDataStructures[0]);
            Assert.IsInstanceOf<ManufacturerSpecificDataAdvertisingDataStructure>(advertisingAndScanResponseData.AdvertisingDataStructures[1]);

            Assert.AreEqual(FlagsAdvertisingDataStructure.FlagsEnum.LEGeneralDiscoverableMode | FlagsAdvertisingDataStructure.FlagsEnum.BR_EDR_NotSupported, (advertisingAndScanResponseData.AdvertisingDataStructures[0] as FlagsAdvertisingDataStructure).ValueBitField);
            Assert.AreEqual(25, (advertisingAndScanResponseData.AdvertisingDataStructures[1] as ManufacturerSpecificDataAdvertisingDataStructure).Data.Length);
        }

        [Test]
        public void Decode_AdvertisingAndScanResponseData_BlueBeacon()
        {
            string hex = "02 01 06 1A FF 4C 00 02 15 E2 C5 6D B5 DF FB 48 D2 B0 60 D0 F5 A7 10 96 E0 00 01 00 00 C6 ";

            byte[] buf = TestHelpers.StringToByteArray(hex);

            AdvertisingAndScanResponseData advertisingAndScanResponseData = AdvertisingAndScanResponseDataParser.Parse(buf);

            Assert.IsTrue(ManufacturerSpecificData_iBeacon.CanBeCreatedFromManufacturerSpecificData(advertisingAndScanResponseData.AdvertisingDataStructures[1] as ManufacturerSpecificDataAdvertisingDataStructure));

            ManufacturerSpecificData_iBeacon manufacturerSpecificData_iBeacon = ManufacturerSpecificData_iBeacon.CreateFromManufacturerSpecificData(advertisingAndScanResponseData.AdvertisingDataStructures[1] as ManufacturerSpecificDataAdvertisingDataStructure);

            Assert.AreEqual(TI_BLE_HCI_ClientLib.DataEntities.AssignedNumbers.CompanyIdentifier.Apple, manufacturerSpecificData_iBeacon.CompanyIdentifier);
            Assert.AreEqual(0x1502, manufacturerSpecificData_iBeacon.AdvertisementIndicator);
            Assert.AreEqual(TestHelpers.StringToByteArray("E2 C5 6D B5 DF FB 48 D2 B0 60 D0 F5 A7 10 96 E0 "), manufacturerSpecificData_iBeacon.ProximityUUID);
            Assert.AreEqual(0x0001, manufacturerSpecificData_iBeacon.Major);
            Assert.AreEqual(0x0000, manufacturerSpecificData_iBeacon.Minor);
            Assert.AreEqual(-58, manufacturerSpecificData_iBeacon.TxCalibratedPower);

            Assert.IsTrue(manufacturerSpecificData_iBeacon.IsAppleiBeacon);
        }


        [Test]
        public void Decode_AdvertisingAndScanResponseData_BlueBeacon_2()
        {
            string hex = "0B 09 42 6C 75 65 42 65 61 63 6F 6E 05 12 50 00 20 03 02 0A 00";

            byte[] buf = TestHelpers.StringToByteArray(hex);

            AdvertisingAndScanResponseData advertisingAndScanResponseData = AdvertisingAndScanResponseDataParser.Parse(buf);

            Assert.AreEqual(2, advertisingAndScanResponseData.AdvertisingDataStructures.Length);
            Assert.AreEqual(AdvertisingDataStructureTypeEnum.CompleteLocalName, advertisingAndScanResponseData.AdvertisingDataStructures[0].Type);
            Assert.AreEqual(AdvertisingDataStructureTypeEnum.TxPowerLevel, advertisingAndScanResponseData.AdvertisingDataStructures[1].Type);
            Assert.IsInstanceOf(typeof(LocalNameAdvertisingDataStructure), advertisingAndScanResponseData.AdvertisingDataStructures[0]);
            Assert.IsInstanceOf(typeof(TxPowerLevelAdvertisingDataStructure), advertisingAndScanResponseData.AdvertisingDataStructures[1]);
            Assert.AreEqual("BlueBeacon", (advertisingAndScanResponseData.AdvertisingDataStructures[0] as LocalNameAdvertisingDataStructure).DeviceName);
            Assert.AreEqual(0, (advertisingAndScanResponseData.AdvertisingDataStructures[1] as TxPowerLevelAdvertisingDataStructure).TxPowerLevel);
        }

        [Test]
        public void Decode_AdvertisingAndScanResponseData_TISensorTag()
        {
            string hex = "0A 09 53 65 6E 73 6F 72 54 61 67 05 12 50 00 20 03 02 0A 00";

            byte[] buf = TestHelpers.StringToByteArray(hex);

            AdvertisingAndScanResponseData advertisingAndScanResponseData = AdvertisingAndScanResponseDataParser.Parse(buf);

            Assert.AreEqual(2, advertisingAndScanResponseData.AdvertisingDataStructures.Length);
            Assert.AreEqual(AdvertisingDataStructureTypeEnum.CompleteLocalName, advertisingAndScanResponseData.AdvertisingDataStructures[0].Type);
            Assert.AreEqual(AdvertisingDataStructureTypeEnum.TxPowerLevel, advertisingAndScanResponseData.AdvertisingDataStructures[1].Type);
            Assert.IsInstanceOf(typeof(LocalNameAdvertisingDataStructure), advertisingAndScanResponseData.AdvertisingDataStructures[0]);
            Assert.IsInstanceOf(typeof(TxPowerLevelAdvertisingDataStructure), advertisingAndScanResponseData.AdvertisingDataStructures[1]);
            Assert.AreEqual("SensorTag", (advertisingAndScanResponseData.AdvertisingDataStructures[0] as LocalNameAdvertisingDataStructure).DeviceName);
            Assert.AreEqual(0, (advertisingAndScanResponseData.AdvertisingDataStructures[1] as TxPowerLevelAdvertisingDataStructure).TxPowerLevel);
        }

        [Test]
        public void Decode_AdvertisingAndScanResponseData_TIKeyFob()
        {
            string hex = "02 01 05 07 02 03 18 02 18 04 18";

            byte[] buf = TestHelpers.StringToByteArray(hex);

            AdvertisingAndScanResponseData advertisingAndScanResponseData = AdvertisingAndScanResponseDataParser.Parse(buf);

            Assert.AreEqual(2, advertisingAndScanResponseData.AdvertisingDataStructures.Length);
            Assert.AreEqual(AdvertisingDataStructureTypeEnum.Flags, advertisingAndScanResponseData.AdvertisingDataStructures[0].Type);
            Assert.AreEqual(AdvertisingDataStructureTypeEnum.IncompleteListOf16BitServiceClassUUIDs, advertisingAndScanResponseData.AdvertisingDataStructures[1].Type);
            Assert.IsInstanceOf(typeof(FlagsAdvertisingDataStructure), advertisingAndScanResponseData.AdvertisingDataStructures[0]);
            Assert.IsInstanceOf(typeof(IncompleteListOf16BitServiceUUIDsAdvertisingDataStructure), advertisingAndScanResponseData.AdvertisingDataStructures[1]);
            Assert.AreEqual(FlagsAdvertisingDataStructure.FlagsEnum.BR_EDR_NotSupported | FlagsAdvertisingDataStructure.FlagsEnum.LELimitedDiscoverableMode, (advertisingAndScanResponseData.AdvertisingDataStructures[0] as FlagsAdvertisingDataStructure).ValueBitField);
            Assert.AreEqual(3, (advertisingAndScanResponseData.AdvertisingDataStructures[1] as IncompleteListOf16BitServiceUUIDsAdvertisingDataStructure).ServiceUUIDs.Length);
            Assert.AreEqual(0x1803, (advertisingAndScanResponseData.AdvertisingDataStructures[1] as IncompleteListOf16BitServiceUUIDsAdvertisingDataStructure).ServiceUUIDs[0]);
            Assert.AreEqual(0x1802, (advertisingAndScanResponseData.AdvertisingDataStructures[1] as IncompleteListOf16BitServiceUUIDsAdvertisingDataStructure).ServiceUUIDs[1]);
            Assert.AreEqual(0x1804, (advertisingAndScanResponseData.AdvertisingDataStructures[1] as IncompleteListOf16BitServiceUUIDsAdvertisingDataStructure).ServiceUUIDs[2]);
        }

        [Test]
        public void Encode_and_Decode_AdvertisingAndScanResponseData_Roundtrip()
        {
            // Avertising Data (Flags e CompleteDeviceName)
            var adData1 = new AdvertisingAndScanResponseData();

            adData1.addAdvertisingDataStructure(new FlagsAdvertisingDataStructure(FlagsAdvertisingDataStructure.FlagsEnum.LEGeneralDiscoverableMode | FlagsAdvertisingDataStructure.FlagsEnum.BR_EDR_NotSupported));
            adData1.addAdvertisingDataStructure(new LocalNameAdvertisingDataStructure(AdvertisingDataStructureTypeEnum.CompleteLocalName, "name"));
            adData1.addAdvertisingDataStructure(new IncompleteListOf16BitServiceUUIDsAdvertisingDataStructure(new ushort[] { 0x1801, 0xFF01, 0xFF02, 0xFF03 }));

            AdvertisingAndScanResponseData adData2 = AdvertisingAndScanResponseDataParser.Parse(adData1.ToByteArray());

            Assert.AreEqual(3, adData2.AdvertisingDataStructures.Length);

            Assert.AreEqual(AdvertisingDataStructureTypeEnum.Flags, adData2.AdvertisingDataStructures[0].Type);
            Assert.AreEqual(AdvertisingDataStructureTypeEnum.CompleteLocalName, adData2.AdvertisingDataStructures[1].Type);
            Assert.AreEqual(AdvertisingDataStructureTypeEnum.IncompleteListOf16BitServiceClassUUIDs, adData2.AdvertisingDataStructures[2].Type);

            Assert.IsInstanceOf(typeof(FlagsAdvertisingDataStructure), adData2.AdvertisingDataStructures[0]);
            Assert.IsInstanceOf(typeof(LocalNameAdvertisingDataStructure), adData2.AdvertisingDataStructures[1]);
            Assert.IsInstanceOf(typeof(IncompleteListOf16BitServiceUUIDsAdvertisingDataStructure), adData2.AdvertisingDataStructures[2]);

            Assert.AreEqual((adData1.AdvertisingDataStructures[0] as FlagsAdvertisingDataStructure).ValueBitField, (adData2.AdvertisingDataStructures[0] as FlagsAdvertisingDataStructure).ValueBitField);
            Assert.AreEqual((adData1.AdvertisingDataStructures[1] as LocalNameAdvertisingDataStructure).DeviceName, (adData2.AdvertisingDataStructures[1] as LocalNameAdvertisingDataStructure).DeviceName);
            Assert.AreEqual((adData1.AdvertisingDataStructures[2] as IncompleteListOf16BitServiceUUIDsAdvertisingDataStructure).ServiceUUIDs, (adData2.AdvertisingDataStructures[2] as IncompleteListOf16BitServiceUUIDsAdvertisingDataStructure).ServiceUUIDs);
        }
    }
}